#include <iostream>

#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
#include <stdlib.h>
#include <cassert>
#include <sys/epoll.h>
#include "message.h"
#include <stdio.h>

// 客户端连接上下文
struct ClientContext {
    std::vector<uint8_t> recv_buffer; // 接收缓冲区
    uint64_t last_active;            // 最后活跃时间戳
    // 可添加其他状态信息：用户名、权限等
};

std::unordered_map<int, ClientContext> clients;

class server
{
public:
    // network
    int listen_fd;
    int epoll_fd;

    epoll_event events[512];

public:
    server() = default;
    // 析构
    ~server()
    {
        if (listen_fd >= 0)
            close(listen_fd);
        if (epoll_fd >= 0)
            close(epoll_fd);
    }
    void eventListen()
    {
        listen_fd = socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, 0);
        assert(listen_fd >= 0);

        int ret = 0;
        struct sockaddr_in address;
        bzero(&address, sizeof(address));
        address.sin_family = AF_INET;
        address.sin_addr.s_addr = inet_addr("127.0.0.1");
        address.sin_port = htons(8888);

        int flag = 1;
        setsockopt(listen_fd, SOL_SOCKET, SO_REUSEADDR, &flag, sizeof(flag));
        ret = bind(listen_fd, (struct sockaddr *)&address, sizeof(address));
        assert(ret != -1);
        ret = listen(listen_fd, 5);
        assert(ret != -1);

        epoll_fd = epoll_create(5);
        assert(epoll_fd != -1);

        // 添加监听socket到epoll
        struct epoll_event ev;
        ev.events = EPOLLIN | EPOLLET; // 边缘触发模式
        ev.data.fd = listen_fd;
        if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, listen_fd, &ev) < 0)
        {
            perror("epoll_ctl add listen_fd failed");
            close(listen_fd);
            close(epoll_fd);
            exit(EXIT_FAILURE);
        }
    }

    void eventLoop()
    {
        while (true)
        {
            int number = epoll_wait(epoll_fd, events, 512, -1);
            if (number < 0 && errno != EINTR)
            {
                perror("epoll failure");
                break;
            }

            for (int i = 0; i < number; i++)
            {
                int sockfd = events[i].data.fd;
                if (sockfd == listen_fd)
                {
                    handleNewConnection();
                    printf("handleNewConnection\n");
                    continue;
                }

                // 处理错误事件
                if (events[i].events & (EPOLLERR | EPOLLHUP | EPOLLRDHUP))
                {
                    closeClient(sockfd);
                    continue;
                }

                // 处理可读事件
                if (events[i].events & EPOLLIN)
                {
                    handleClientInput(sockfd);
                    continue;
                }
            }
        }
    }
    // 处理新连接
    void handleNewConnection()
    {
        struct sockaddr_in client_addr;
        socklen_t addrlen = sizeof(client_addr);

        while (true)
        { // ET模式需要循环accept
            int client_fd = accept4(listen_fd, (struct sockaddr *)&client_addr,
                                    &addrlen, SOCK_NONBLOCK);
            if (client_fd == -1)
            {
                if (errno == EAGAIN || errno == EWOULDBLOCK)
                    break;
                throw std::system_error(errno, std::generic_category(), "accept failed");
            }

            // 添加到epoll监控
            struct epoll_event ev;
            ev.events = EPOLLIN | EPOLLET | EPOLLRDHUP;
            ev.data.fd = client_fd;
            if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, client_fd, &ev) == -1)
            {
                close(client_fd);
                continue;
            }

            // 初始化客户端上下文
            clients[client_fd] = {
                .recv_buffer = {},
                .last_active = get_timestamp()};
        }
    }

    // 处理客户端输入（边缘触发模式）
    void handleClientInput(int fd)
    {
        auto &ctx = clients[fd];
        char buf[4096];

        while (true)
        { // ET模式必须循环读取直到EAGAIN
            ssize_t n = recv(fd, buf, sizeof(buf), 0);
            if (n == -1)
            {
                if (errno == EAGAIN || errno == EWOULDBLOCK)
                    break;
                closeClient(fd);
                return;
            }
            if (n == 0)
            { // 连接关闭
                closeClient(fd);
                return;
            }

            // 追加到接收缓冲区
            ctx.recv_buffer.insert(ctx.recv_buffer.end(), buf, buf + n);
            ctx.last_active = get_timestamp();
        }

        // 尝试解析完整报文
        processReceiveBuffer(fd);
    }

    // 处理接收缓冲区
    void processReceiveBuffer(int fd) {
        auto &ctx = clients[fd];
    
        while (true) {
            if (ctx.recv_buffer.size() < sizeof(MessageHeader)) return;
    
            // 解析协议头（保持原始网络字节序）
            MessageHeader header;
            memcpy(&header, ctx.recv_buffer.data(), sizeof(header));
    
            // 验证魔数（需转换字节序）
            if (ntohs(header.magic) != 0x1234) {
                closeClient(fd);
                return;
            }
    
            // 提取 body_len（需转换字节序）
            size_t body_len = ntohs(header.body_len);
            size_t total_len = sizeof(header) + body_len;
            if (ctx.recv_buffer.size() < total_len) return;
    
            // 备份校验和
            uint32_t recv_crc = header.checksum;
    
            // 清零校验和字段
            header.checksum = 0;
    
            // 计算校验和（使用原始网络字节序的 header 和 body 数据）
            uint32_t computed_crc = compute_checksum(
                header,
                reinterpret_cast<const uint8_t*>(ctx.recv_buffer.data() + sizeof(header)),
                body_len
            );
    
            // 转换接收到的校验和为本地字节序（用于比对）
            uint32_t recv_crc_host = ntohl(recv_crc);
    
            printf("校验和比对: recv(ntohl)=%u recv=%u\n", recv_crc_host, recv_crc);
            if (recv_crc_host != computed_crc) {
                printf("校验和错误 fd=%d\n", fd);
                closeClient(fd);
                return;
            }
    
            // 转换整个 header 到主机字节序
            header.ntoh();
    
            // 处理报文
            handleMessage(fd, header, ctx.recv_buffer.data() + sizeof(header));
    
            // 移除已处理数据
            ctx.recv_buffer.erase(ctx.recv_buffer.begin(), ctx.recv_buffer.begin() + total_len);
        }
    }
    

    // 关闭客户端连接
    void closeClient(int fd)
    {
        epoll_ctl(epoll_fd, EPOLL_CTL_DEL, fd, nullptr);
        close(fd);
        clients.erase(fd);
        printf("客户端断开连接 fd=%d\n", fd);
    }

    // 消息分发处理
    void handleMessage(int fd, const MessageHeader &header, const uint8_t *body)
    {
        try
        {
            switch (header.msg_type)
            {
            case MessageType::LOGIN_REQ:
                handleLogin(fd, body, header.body_len);
                break;
            case MessageType::GROUP_MSG_SEND:
                handleGroupMessage(fd, body, header.body_len);
                break;
            case MessageType::HEARTBEAT:
                handleHeartbeat(fd);
                break;
            case MessageType::REGISTER_REQ:
                handleRegister(fd, body, header.body_len);
                break;
            default:
                printf("未知消息类型: %d\n", header.msg_type);
                break;
            }
        }
        catch (const std::exception &e)
        {
            printf("处理消息失败: %s\n", e.what());
            closeClient(fd);
        }
    }

    void handleLogin(int fd, const uint8_t *body, size_t len)
    {
        LoginRequest req = LoginRequest::from_json(json::parse(body, body + len));

        printf ("收到登录请求: %s\n", req.username.c_str());
        printf ("收到登录请求password: %s\n", req.password.c_str());
    }
    void handleGroupMessage(int fd, const uint8_t *body, size_t len)
    {

    }

    void handleHeartbeat(int fd)
    {

    }

    void handleRegister(int fd, const uint8_t *body, size_t len)
    {

    }
};
int main()
{
    server s;
    s.eventListen();
    s.eventLoop();

    return 0;
}